﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace WinformPratice
{
    public partial class TreeViewDemo : Form
    {
        public TreeViewDemo()
        {
            InitializeComponent();
        }

        //递归子节点跟随其全选或全不选
        private void ChangeChild(TreeNode node, bool state)
        {
            node.Checked = state;
            foreach (TreeNode tn in node.Nodes)
                ChangeChild(tn, state);
        }

        //递归父节点跟随其全选或全不选
        private void ChangeParent(TreeNode node)
        {
            if (node.Parent != null)
            {
                //兄弟节点被选中的个数
                int brotherNodeCheckedCount = 0;
                //遍历该节点的兄弟节点
                foreach (TreeNode tn in node.Parent.Nodes)
                {
                    if (tn.Checked == true)
                        brotherNodeCheckedCount++;
                }
                //兄弟节点有一个没选择不选
                if (brotherNodeCheckedCount < node.Parent.Nodes.Count)
                {
                    node.Parent.Checked = false;
                    ChangeParent(node.Parent);
                }
                //兄弟节点只要有一个被选，其父节点也被选
                if (brotherNodeCheckedCount == node.Parent.Nodes.Count)
                {
                    node.Parent.Checked = true;
                    ChangeParent(node.Parent);
                }
            }
        }

        private void treeView1_MouseClick(object sender, MouseEventArgs e)
        {
            TreeNode node = treeView1.GetNodeAt(new Point(e.X, e.Y));
            if (node != null)
            {
                ChangeChild(node, node.Checked);//影响子节点
                ChangeParent(node);//影响父节点
            }
        }


        private void GetSelectedTreeNode(TreeNodeCollection nodes, List<TreeNode> selectedNodes)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.Checked)
                {
                    selectedNodes.Add(node);
                }
                GetSelectedTreeNode(node.Nodes, selectedNodes);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            String a = "";
            List<TreeNode> selectedNodes = new List<TreeNode>();
            GetSelectedTreeNode(treeView1.Nodes, selectedNodes);
            foreach (TreeNode node in selectedNodes)
            {
                a += node.Tag + ",";
            }
            MessageBox.Show(a.Trim(','));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            treeView1.SelectedNode.Nodes.Add(new TreeNode() { Name = "新增", Tag = "hahaha", Text = "新增" });
        }

        private void button3_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            String url = textBox1.Text;
            //提取店铺地址
            Regex regex = new Regex(@"([^/]*com)");
            Match match = regex.Match(url);
            String shopUrl = match.Value;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://" + shopUrl + "/category.htm");
            request.Method = "GET";
            request.Accept = "text/html, application/xhtml+xml, */*";
            request.Headers.Add("Accept-Language", "zh-CN;");
            request.Referer = "www.taobao.com";
            request.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
            request.Headers.Add("Accept-Encoding", "gzip, deflate;");
            request.Host = shopUrl;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            myResponseStream = new GZipStream(myResponseStream, CompressionMode.Decompress);
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("gb2312"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            //richTextBox1.Text = retString;

            HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
            document.LoadHtml(retString);

            HtmlNode rootNode = document.DocumentNode;
            HtmlNodeCollection nodeList = rootNode.SelectNodes("//ul[@class='J_TAllCatsTree cats-tree']/li");

            foreach (HtmlNode node in nodeList)
            {
                HtmlNode fstChild = node.SelectSingleNode(".//a[contains(@class,'fst-cat-name')]");
                TreeNode fstChildTreeNode = new TreeNode() { Name = fstChild.InnerText.Trim(), Tag = fstChild.Attributes["href"].Value, Text = fstChild.InnerText.Trim() };
                treeView1.Nodes.Add(fstChildTreeNode);
                HtmlNodeCollection sndChild = node.SelectNodes(".//ul[contains(@class,'fst-cat-bd')]//a[contains(@class,'cat-name')]");
                if (sndChild != null)
                {
                    foreach (HtmlNode sndChildNode in sndChild)
                    {
                        fstChildTreeNode.Nodes.Add(new TreeNode() { Name = sndChildNode.InnerText.Trim(), Tag = sndChildNode.Attributes["href"].Value, Text = sndChildNode.InnerText.Trim() });
                    }
                }
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            List<TreeNode> selectedNodes = new List<TreeNode>();
            GetSelectedTreeNode(treeView1.Nodes, selectedNodes);
            IList<Product> listProduct = new List<Product>();

            foreach (TreeNode node in selectedNodes)
            {
                IList<Product> ret = GetProducts(node.Tag.ToString());
                foreach (Product retProduct in ret)
                {
                    bool hasFind = false;
                    foreach (Product product in listProduct)
                    {
                        if (retProduct.DataID == product.DataID)
                        {
                            hasFind = true;
                            break;
                        }
                    }
                    if (hasFind == false)
                    {
                        listProduct.Add(retProduct);
                    }
                }
            }

            foreach (Product product in listProduct)
            {
                richTextBox1.AppendText(product.DataID + "\n");
            }

        }


        private IList<Product> GetProducts(string url)
        {
            String retString = GetResponseString(url);
            IList<Product> retListProduct = GetResponsesProducts(retString);

            HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
            document.LoadHtml(retString);

            HtmlNode rootNode = document.DocumentNode;
            HtmlNode pagNode = rootNode.SelectSingleNode("//div[@class='J_TItems']/div[@class='pagination']/a[@class='J_SearchAsync']");

            int curPage = 2;
            if (pagNode != null)
            {
                string pageUrl = pagNode.Attributes["href"].Value;

                Regex regex = new Regex(@"&pageNo=(\d+)");
                //循环取得分页值
                while (true)
                {
                    String repUrl = regex.Replace(pageUrl, String.Format("&pageNo={0}", curPage));

                    try
                    {
                        String retStr = GetResponseString(repUrl);

                        document.LoadHtml(retStr);

                        rootNode = document.DocumentNode;
                        pagNode = rootNode.SelectSingleNode("//p[@class='item-not-found']");
                        if (pagNode != null)
                        {
                            break;
                        }
                        IList<Product> listProd = GetResponsesProducts(retStr);
                        foreach (Product product in listProd)
                        {
                            bool hasFind = false;
                            foreach (Product retProduct in retListProduct)
                            {
                                if (retProduct.DataID == product.DataID)
                                {
                                    hasFind = true;
                                    break;
                                }
                            }
                            if (hasFind == false)
                            {
                                retListProduct.Add(product);
                            }
                        }
                        curPage++;
                    }
                    catch (Exception e)
                    {
                        break;
                    }
                }
            }
            return retListProduct;
        }


        private string GetResponseString(string url)
        {
            //提取店铺地址
            Regex regex = new Regex(@"([^/]*com)");
            Match match = regex.Match(url);
            String shopUrl = match.Value;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.Accept = "text/html, application/xhtml+xml, */*";
            request.Headers.Add("Accept-Language", "zh-CN;");
            request.Referer = "www.tmall.com";
            request.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
            request.Headers.Add("Accept-Encoding", "gzip, deflate;");
            request.Host = shopUrl;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            myResponseStream = new GZipStream(myResponseStream, CompressionMode.Decompress);
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("gb2312"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            return retString;
        }

        private IList<Product> GetResponsesProducts(String responseString)
        {
            List<Product> listProduct = new List<Product>();

            HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
            document.LoadHtml(responseString);

            HtmlNode rootNode = document.DocumentNode;
            //HtmlNodeCollection nodeList = rootNode.SelectNodes("//div[@class='col-main']//dl[contains(@class,'item')]");
            HtmlNodeCollection nodeList = rootNode.SelectNodes("//div[@class='col-main']//div[@class='pagination']/preceding-sibling::*/dl[contains(@class,'item')]");
            if (nodeList != null)
            {
                foreach (HtmlNode item in nodeList)
                {
                    Product product = new Product();

                    product.DataID = item.Attributes["data-id"].Value;

                    //图片
                    HtmlNode imgNode = item.SelectSingleNode("./dt[@class='photo']/a/img");
                    product.ImgUrl = imgNode.Attributes["src"].Value;

                    //明细
                    HtmlNode detailNode = item.SelectSingleNode("./dd[@class='detail']/a[@class='item-name']");
                    product.Detail = detailNode.InnerText;
                    product.DetailUrl = detailNode.Attributes["href"].Value;

                    //价格
                    HtmlNode priceNode = item.SelectSingleNode("./dd[@class='detail']//span[@class='c-price']");
                    product.Price = Convert.ToDecimal(priceNode.InnerText);

                    //总销售
                    HtmlNode saleNode = item.SelectSingleNode("./dd[@class='detail']//span[@class='sale-num']");
                    if (saleNode != null)
                        product.SaleNum = Convert.ToInt16(saleNode.InnerText);

                    listProduct.Add(product);
                }
            }
            return listProduct;
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
    }
}
